package me.aip.mov.minio;

import io.minio.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * @author aa
 * @description
 */
@Slf4j
public class MinIoUtil {


    private static MinioClient minioClient;
    private static MinIoConfig minIoConfig;

    private final static String minName = "minio";


    public MinIoUtil(MinioClient minioClient, MinIoConfig minIoConfig) {
        MinIoUtil.minioClient = minioClient;
        MinIoUtil.minIoConfig = minIoConfig;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now()));
    }

    /**
     * 验证文件是否存在
     * @param fileName
     * @return
     */
    public  boolean checkFile(String fileName){

        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(minIoConfig.getBucket()).object(fileName).build());
        }catch (Exception e){
            return false;
        }


        return true;
    }

    public  boolean checkPublicFile(String fileName){

        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(minIoConfig.getBucketPublic()).object(fileName).build());
        }catch (Exception e){
            return false;
        }

        return true;
    }
    /**
     * 保存文件  并返文件
     *
     * @param stream      文件流
     * @param fileType    文件类型   图片:img   文本:text
     * @param contentType 文件描述类型
     * @param fileName    文件名称   带后缀
     * @return
     */
    public  String putPrivateFile(InputStream stream, FileTypeEnum fileType, String contentType, String fileName) {

        Boolean aBoolean =false;
        try {
            aBoolean = FileExtensionEnum.checkLength(fileName, null, stream.available());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("文件校验失败，请检查文件类型");
        }
        if (! aBoolean) {
            throw new RuntimeException("文件过大，上传失败");
        }


        StringBuffer newFileName = new StringBuffer()
                .append(fileType.getCode())
                .append("/").append(System.currentTimeMillis())
                .append(Math.random() * 1000 / 1000)
                .append(fileName.substring(fileName.lastIndexOf("."))
                );
        try {
            minioClient.putObject(
                    PutObjectArgs
                            .builder()
                            .bucket(minIoConfig.getBucket())
                            .object(newFileName.toString())
                            .stream(stream, stream.available(), -1)
                            .contentType(contentType)
                            .build());

            return new StringBuffer(minIoConfig.getUrl()).append(minIoConfig.getBucketPublic()).append("/").append(newFileName).toString();
        } catch (Exception e) {

            e.printStackTrace();

            throw new RuntimeException("文件上传失败 {" + fileName + "}");
        }
    }


    /**
     * 保存文件  并返回公网可访问文件
     *
     * @param stream      文件流
     * @param fileType    文件类型   图片:img   文本:text
     * @param contentType 文件描述类型
     * @param fileName    文件名称   带后缀
     * @return
     */
    public  String putAndReturnUrl(InputStream stream, FileTypeEnum fileType, String contentType, String fileName)  {



        Boolean aBoolean =false;
        try {
             aBoolean = FileExtensionEnum.checkLength(fileName, null, stream.available());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("文件校验失败，请检查文件类型");
        }
        if (! aBoolean) {
            throw new RuntimeException("文件过大，上传失败");
        }


        StringBuffer newFileName = new StringBuffer()
                .append(fileType.getCode())
                .append("/").append(DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now()))
                .append("/").append(System.currentTimeMillis())
                .append(Math.random() * 1000 / 1000)
                .append(fileName.substring(fileName.lastIndexOf("."))
                );
        try {
            minioClient.putObject(
                    PutObjectArgs
                            .builder()
                            .bucket(minIoConfig.getBucketPublic())
                            .object(newFileName.toString())
//                            .stream(byteArrayInputStream, stream.available(), -1)
                            .stream(stream, stream.available(), -1)
                            .contentType(contentType)
                            .build());

            return new StringBuffer(minIoConfig.getLoad_url()).append(minIoConfig.getBucketPublic()).append("/").append(newFileName).toString();
        } catch (Exception e) {

            e.printStackTrace();

            throw new RuntimeException("文件上传失败 {" + fileName + "}");
        }
    }

    /**
     * 保存文件  并返回公网可访问文件
     *
     * @param stream      文件流
     * @param contentType 文件描述类型
     * @param fileName    文件名称   带后缀
     * @return
     */
    public  String putNoPackageAndReturnUrl(InputStream stream,  String contentType, String fileName) {

        try {
            minioClient.putObject(
                    PutObjectArgs
                            .builder()
                            .bucket(minIoConfig.getBucketPublic())
                            .object(fileName)
                            .stream(stream, stream.available(), -1)
                            .contentType(contentType)
                            .build());

            return new StringBuffer(minIoConfig.getLoad_url()).append(minIoConfig.getBucketPublic()).append("/").append(fileName).toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传失败 {" + fileName + "}");
        }
    }

    /**
     * 返回要下载的文件流
     *
     * @param fileName
     * @return
     */
    public InputStream readFileToIo(String fileName) {
        InputStream stream = null;
        try {
            stream = minioClient.getObject(
                    GetObjectArgs
                            .builder()
                            .bucket(minIoConfig.getBucket())
                            .object(fileName)
                            .build());
            return stream;
        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }


    private  ByteArrayOutputStream cloneInputStream(InputStream input) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * @Author: 梁龙
     * @Description: 根据url删除文件
     * @DateTime: 2022/3/8 上午9:15
     * @Params: 文件url
     * @Return
     */

    public static void removeFile(String url) {
        String fileName = url.substring(url.lastIndexOf("/") + 1);
        try {
            minioClient.statObject(
                    StatObjectArgs.builder().bucket(minIoConfig.getBucket()).object(fileName).build()
            );
            minioClient.removeObject(
                    RemoveObjectArgs.builder().bucket(minIoConfig.getBucket()).object(fileName).build()
            );
        } catch (Exception e) {
            //记录错误信息
            log.error("删除文件出错,文件名为{},bucket为{}", fileName, minIoConfig.getBucket());
        }
    }

}
